﻿using System;
using System.IO;
using System.Text;
using ExcelDataReader;
using Newtonsoft.Json;

namespace ExcelToJson
{
    public class JsonGenerator
    {
        private string mExportPath = "";
        private PlatformType mPlatformType = PlatformType.None;

        private string className;
        private string[] mFieldArray;
        private string[] mTypeArray;
        private string[] mPlatformArray;
        private string[] mDataArray;

        private StringBuilder stringBuilder;
        private JsonTextWriter jsonTextWriter;

        public void Init(string pExportPath, PlatformType pPlatformType)
        {
            mExportPath = pExportPath;
            mPlatformType = pPlatformType;

            if (!Directory.Exists(mExportPath))
            {
                Directory.CreateDirectory(mExportPath);
            }
        }

        /// <summary>生成Json</summary>
        /// <param name="pConfigPath">配置路径</param>
        public void GenerateJson(FileSystemInfo pFileSystemInfo)
        {
            int index = pFileSystemInfo.Name.IndexOf(".");
            className = pFileSystemInfo.Name.Substring(0, index);
            Reset();
            GenerateJsonCode(pFileSystemInfo.FullName);
            ExportFile();
        }

        private void Reset()
        {
            stringBuilder = new StringBuilder();
            StringWriter stringWriter = new StringWriter(stringBuilder);
            jsonTextWriter = new JsonTextWriter(stringWriter);
            jsonTextWriter.Formatting = Formatting.Indented;
        }

        /// <summary>生成Json代码</summary>
        /// <param name="pConfigPath">配置路径</param>
        private void GenerateJsonCode(string pConfigPath)
        {
            FileStream stream = File.OpenRead(pConfigPath);
            using (IExcelDataReader excelReader = ExcelReaderFactory.CreateReader(stream))
            {
                while (excelReader.Read())
                {
                    if (excelReader.Depth == (int)EnumExcelStruct.Field)
                    {
                        mFieldArray = GetDatas(excelReader);
                    }
                    else if (excelReader.Depth == (int)EnumExcelStruct.Type)
                    {
                        mTypeArray = GetDatas(excelReader);
                    }
                    else if (excelReader.Depth == (int)EnumExcelStruct.Platform)
                    {
                        mPlatformArray = GetDatas(excelReader);
                        if (!CheckPlatform(mPlatformArray[0]))
                            return;
                    }
                    else if (excelReader.Depth >= (int)EnumExcelStruct.Data)
                    {
                        if (excelReader.Depth == (int)EnumExcelStruct.Data)
                            jsonTextWriter.WriteStartArray();

                        string configId = excelReader.GetString(0);
                        if (!string.IsNullOrEmpty(configId))
                        {
                            mDataArray = GetDatas(excelReader);
                            AppendJson(mTypeArray, mFieldArray, mPlatformArray, mDataArray);
                        }
                    }
                }

                jsonTextWriter.WriteEnd();
                excelReader.Close();
            }
        }

        /// <summary>获取数据</summary>
        /// <param name="excelReader">excelReader</param>
        private string[] GetDatas(IExcelDataReader excelReader)
        {
            string[] datas = new string[excelReader.FieldCount];
            for (int i = 0; i < excelReader.FieldCount; i++)
            {
                datas[i] = excelReader.GetString(i);
            }
            return datas;
        }

        /// <summary>检测平台</summary>
        /// <param name="pPlatformKey"></param>
        private bool CheckPlatform(string pPlatformKey)
        {
            if (mPlatformType == PlatformType.Client && (pPlatformKey == PlatformDefine.cCSKey || pPlatformKey == PlatformDefine.cCKey))
                return true;
            else if (mPlatformType == PlatformType.Server && (pPlatformKey == PlatformDefine.cCSKey || pPlatformKey == PlatformDefine.cSKey))
                return true;
            else
                return false;
        }

        /// <summary>添加Json</summary>
        /// <param name="types">类型</param>
        /// <param name="fields">字段名</param>
        /// <param name="datas">数据</param>
        private void AppendJson(string[] types, string[] fields, string[] platform, string[] datas)
        {
            jsonTextWriter.WriteStartObject();
            for (int i = 0; i < types.Length; i++)
            {
                if (!CheckPlatform(platform[i]))
                    continue;

                switch (types[i])
                {
                    case TypeDefine.cBool:
                        AppendBool(fields[i], datas[i]);
                        break;
                    case TypeDefine.cBoolArray:
                        AppendBoolArray(fields[i], datas[i]);
                        break;
                    case TypeDefine.cInt:
                        AppendInt(fields[i], datas[i]);
                        break;
                    case TypeDefine.cIntArray:
                        AppendIntArray(fields[i], datas[i]);
                        break;
                    case TypeDefine.cFloat:
                        AppendFloat(fields[i], datas[i]);
                        break;
                    case TypeDefine.cFloatArray:
                        AppendFloatArray(fields[i], datas[i]);
                        break;
                    case TypeDefine.cString:
                        AppendString(fields[i], datas[i]);
                        break;
                    case TypeDefine.cStringArray:
                        AppendStringArray(fields[i], datas[i]);
                        break;
                }
            }
            jsonTextWriter.WriteEndObject();
        }

        private void AppendBool(string field, string data)
        {
            jsonTextWriter.WritePropertyName(field);
            if (data == "true")
                jsonTextWriter.WriteValue(true);
            else if (data == "false")
                jsonTextWriter.WriteValue(false);
        }

        private void AppendBoolArray(string field, string data)
        {
            jsonTextWriter.WritePropertyName(field);
            jsonTextWriter.WriteStartArray();

            data = data.Replace("[", "");
            data = data.Replace("]", "");
            string[] dataArray = data.Split(',');
            for (int i = 0; i < dataArray.Length; i++)
            {
                if (dataArray[i] == "true")
                    jsonTextWriter.WriteValue(true);
                else if (dataArray[i] == "false")
                    jsonTextWriter.WriteValue(false);
            }

            jsonTextWriter.WriteEndArray();
        }

        private void AppendInt(string field, string data)
        {
            jsonTextWriter.WritePropertyName(field);
            jsonTextWriter.WriteValue(int.Parse(data));
        }

        private void AppendIntArray(string field, string data)
        {
            jsonTextWriter.WritePropertyName(field);
            jsonTextWriter.WriteStartArray();

            data = data.Replace("[", "");
            data = data.Replace("]", "");
            string[] dataArray = data.Split(',');
            for (int i = 0; i < dataArray.Length; i++)
            {
                int value = int.Parse(dataArray[i]);
                jsonTextWriter.WriteValue(value);
            }

            jsonTextWriter.WriteEndArray();
        }

        private void AppendFloat(string field, string data)
        {
            jsonTextWriter.WritePropertyName(field);
            jsonTextWriter.WriteValue(float.Parse(data));
        }

        private void AppendFloatArray(string field, string data)
        {
            jsonTextWriter.WritePropertyName(field);
            jsonTextWriter.WriteStartArray();

            data = data.Replace("[", "");
            data = data.Replace("]", "");
            string[] dataArray = data.Split(',');
            for (int i = 0; i < dataArray.Length; i++)
            {
                float value = float.Parse(dataArray[i]);
                jsonTextWriter.WriteValue(value);
            }

            jsonTextWriter.WriteEndArray();
        }

        private void AppendString(string field, string data)
        {
            jsonTextWriter.WritePropertyName(field);
            jsonTextWriter.WriteValue(data);
        }

        private void AppendStringArray(string field, string data)
        {
            jsonTextWriter.WritePropertyName(field);
            jsonTextWriter.WriteStartArray();

            data = data.Replace("[", "");
            data = data.Replace("]", "");
            string[] dataArray = data.Split(',');
            for (int i = 0; i < dataArray.Length; i++)
            {
                jsonTextWriter.WriteValue(dataArray[i]);
            }

            jsonTextWriter.WriteEndArray();
        }

        /// <summary>输出文件</summary>
        private void ExportFile()
        {
            if (CheckPlatform(mPlatformArray[0]))
            {
                string path = string.Format("{0}/{1}.json", mExportPath, className);
                string content = stringBuilder.ToString();
                File.WriteAllText(path, content);
            }
        }
    }
}